package mark.tom.fiter;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.net.UnknownServiceException;

import mark.tom.fiter.bean.config.RequestConfig;
import mark.tom.fiter.constants.StatusCodeEnums;

import static mark.tom.fiter.Utils.runOnMainThread;
import static mark.tom.fiter.constants.StatusCodeConstants.CONNECT_ERROR_CODE;
import static mark.tom.fiter.constants.StatusCodeConstants.SOCKET_TIMEOUT_ERROR_CODE;
import static mark.tom.fiter.constants.StatusCodeConstants.UNKNOWN_ERROR_CODE;
import static mark.tom.fiter.constants.StatusCodeConstants.UNKNOWN_HOST_ERROR_CODE;
import static mark.tom.fiter.constants.StatusCodeConstants.UNKNOWN_SERVICE_ERROR_CODE;

public class NetErrorInterceptorFactory extends NetErrorInterceptor.Factory {

    @Override
    public NetErrorInterceptor get() {
        return get(null);
    }

    public NetErrorInterceptor get(@Nullable IErrorHandler netErrorToastProvider) {
        return new DefaultNetErrorInterceptor(netErrorToastProvider);
    }

    private final static class DefaultNetErrorInterceptor implements NetErrorInterceptor {

        @Nullable
        final IErrorHandler errorHandler;

        DefaultNetErrorInterceptor(@Nullable IErrorHandler errorHandler) {
            this.errorHandler = errorHandler;
        }

        @Override
        public int intercept(@NonNull Throwable throwable) {
            int statusCode;
            if (throwable instanceof SocketTimeoutException) {
                statusCode = SOCKET_TIMEOUT_ERROR_CODE;
            } else if (throwable instanceof ConnectException) {
                statusCode = CONNECT_ERROR_CODE;
            } else if (throwable instanceof UnknownHostException) {
                statusCode = UNKNOWN_HOST_ERROR_CODE;
            } else if (throwable instanceof UnknownServiceException) {
                statusCode = UNKNOWN_SERVICE_ERROR_CODE;
            } else {
                statusCode = UNKNOWN_ERROR_CODE;
            }
            return statusCode;
        }

        @Override
        public void handle(@StatusCodeEnums final int statusCode, @Nullable final String msg, @Nullable RequestConfig mRequestConfig) {
            runOnMainThread(new Runnable() {
                @Override
                public void run() {
                    if (null == errorHandler) {
                        return;
                    }
                    errorHandler.handlerError(statusCode, msg);
                }
            });
        }
    }

    public interface IErrorHandler {

        void handlerError(@StatusCodeEnums int statusCode, @Nullable String msg);
    }
}
